package com.seeyoui.kensite.bussiness.exam.examResult.util;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.seeyoui.kensite.bussiness.exam.common.Const;
import com.seeyoui.kensite.bussiness.exam.common.Method;
import com.seeyoui.kensite.bussiness.exam.exam.service.ExamQueryService;
import com.seeyoui.kensite.bussiness.exam.exam.service.ExamService;
import com.seeyoui.kensite.bussiness.exam.examResult.domain.ExamResult;
import com.seeyoui.kensite.bussiness.exam.examResult.service.ExamResultService;
import com.seeyoui.kensite.bussiness.exam.exercise.domain.Exercise;
import com.seeyoui.kensite.bussiness.exam.exercise.service.ExerciseService;
import com.seeyoui.kensite.bussiness.exam.paper.domain.Paper;
import com.seeyoui.kensite.bussiness.exam.paper.service.PaperService;
import com.seeyoui.kensite.bussiness.exam.question.domain.Question;
import com.seeyoui.kensite.bussiness.exam.question.domain.QuestionVO;
import com.seeyoui.kensite.bussiness.exam.question.service.QuestionService;
import com.seeyoui.kensite.common.exception.CRUDException;
import com.seeyoui.kensite.common.util.Formatter;
import com.seeyoui.kensite.common.util.SpringContextHolder;
import com.seeyoui.kensite.common.util.StringUtils;

/**
 * 评分处理类 Marking
 * 
 * @author dico
 * @version 2.0
 * @since 1.0
 * @date 2018-01-08
 */

public class Marking {
	private static Logger logger = LoggerFactory.getLogger(Marking.class);

	public static ExamResultService examResultService = SpringContextHolder.getBean(ExamResultService.class);
	public static PaperService paperService = SpringContextHolder.getBean(PaperService.class);
	public static ExamService examService = SpringContextHolder.getBean(ExamService.class);
	public static ExamQueryService examQueryService = SpringContextHolder.getBean(ExamQueryService.class);
	public static QuestionService questionService = SpringContextHolder.getBean(QuestionService.class);
	public static ExerciseService exerciseService = SpringContextHolder.getBean(ExerciseService.class);

	/**
	 * 根据ID查询单条数据
	 * 
	 * @param id
	 * @return
	 * @throws CRUDException
	 */
	public void startMarking(String examId) {
		logger.info("开始评分...");
		Paper paper = paperService.findByExamId(examId);
		List<QuestionVO> lsQuestionVOs = examQueryService.findListQuestionByExamId(examId);
		Map<String, QuestionVO> mapId2QuestionVO = Method.convertListToMap(lsQuestionVOs);

		List<ExamResult> lsExamResults = examResultService.findByExamId(examId);

		for (ExamResult examResult : lsExamResults) {
			if (StringUtils.isEmpty(examResult.getResult())) {
				continue;
			}
			marking(paper, mapId2QuestionVO, examResult);
		}
		
		// 将考试名次写入Remarks字段，格式：名次/试卷总数
		lsExamResults = examResultService.findByExamId(examId);
		int total = lsExamResults.size();
		for (int i = 0; i < total; i++) {
			lsExamResults.get(i).setRemarks((i + 1) + "/" + total);
			examResultService.update(lsExamResults.get(i));
		}
		
		logger.info("评分结束...");
	}
	
	/**
	 * 开始为指定的练习评分
	 * @param exercise
	 */
	public void startMarkingExercise(Exercise exercise) {
		logger.info("开始评分...");
		@SuppressWarnings("unchecked")
		Map<String, String> mapResults = (Map<String, String>) JSON.parse(exercise.getResult());
		
		int score = 0; // 用户得分
		for (Entry<String, String> entry : mapResults.entrySet()) {
			Question question = questionService.findOne(entry.getKey());
			if (null == question) {
				continue;
			}
			String userAnswer = entry.getValue();
			if(StringUtils.isEmpty(userAnswer)) {
				continue;
			}
			userAnswer = userAnswer.replaceAll(",", "").trim();
			
			if (question.getAnswer().equalsIgnoreCase(userAnswer)) {
				// 回答正确correct
				score += 1;
			}
		}

		exercise.setMarking("1"); // 标记为已评分
		exercise.setScore(String.valueOf(score)); // 设置得分
		exerciseService.update(exercise);
		
		logger.info("评分结束...");
	}

	/**
	 * 给指定的试卷答案评分
	 * 
	 * @param paper
	 * @param mapId2QuestionVO
	 * @param examResult
	 */
	private void marking(Paper paper, Map<String, QuestionVO> mapId2QuestionVO, ExamResult examResult) {
		@SuppressWarnings("unchecked")
		Map<String, String> mapResults = (Map<String, String>) JSON.parse(examResult.getResult());
		
		int score = 0; // 用户得分
		for (Entry<String, String> entry : mapResults.entrySet()) {
			QuestionVO questionVO = mapId2QuestionVO.get(entry.getKey());
			if (null == questionVO) {
				continue;
			}
			String userAnswer = entry.getValue();
			if(StringUtils.isEmpty(userAnswer)) {
				continue;
			}
			userAnswer = userAnswer.replaceAll(",", "").trim();
			
			if (questionVO.getAnswer().equalsIgnoreCase(userAnswer)) {
				// 回答正确correct
				switch (questionVO.getQuestionTypeId()) {
				case Const.QUESTION_TYPE_ID_SINGLE:
					score += Formatter.stringToInt(paper.getSingleScore());
					break;
				case Const.QUESTION_TYPE_ID_MULTIPLE:
					score += Formatter.stringToInt(paper.getMultipleScore());
					break;
				case Const.QUESTION_TYPE_ID_JUDGE:
					score += Formatter.stringToInt(paper.getJudgeScore());
					break;
				default:
					break;
				}
			}
		}
		examResult.setMarking("1"); // 标记为已评分
		examResult.setScore(String.valueOf(score)); // 设置得分
		rewardPoint(paper, examResult, score); // 奖励积分
		examResultService.update(examResult);
	}

	/**
	 * 奖励积分<br>
	 * 该考试奖励积分：固定规则如下<br>
	 * 得分在总分的70%~80%：奖励积分5<br>
	 * 得分在总分的80%~90%：奖励积分10<br>
	 * 得分在总分的90%~100%：奖励积分20<br>
	 * 满分额外奖励10个积分<br>
	 * 
	 * @param paper
	 * @param examResult
	 * @param score
	 */
	private void rewardPoint(Paper paper, ExamResult examResult, int score) {
		int totalScore = Formatter.stringToInt(paper.getTotalScore());
		int level = score * 100 / totalScore;
		if (level >= 70 && level < 80) {
			examResult.setPoint("5");
		} else if (level >= 80 && level < 90) {
			examResult.setPoint("10");
		} else if (level >= 90 && level < 100) {
			examResult.setPoint("20");
		} else if (level == 100) {
			examResult.setPoint("30");
		}
	}
}